package com.login.sotoken.controller.user;


import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.dev33.satoken.util.SaResult;
import com.login.sotoken.annotation.SaUserCheckLogin;
import com.login.sotoken.req.LoginListReq;
import com.login.sotoken.resp.LoginGetResp;
import com.login.sotoken.utils.StpUserUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

/**
 * 登录测试
 *
 * @author click33
 */
@Slf4j
@Tag(name = "用户端登录管理", description = "用户端登录管理接口")
@RestController
@RequestMapping("/login/user")
public class UserLoginController {

    @Operation(summary = "登录")
    @PostMapping("doLogin")
    public SaResult doLogin(@Valid @RequestBody LoginListReq req) {
        // 此处仅作模拟示例，真实项目需要从数据库中查询数据进行比对
        if ("zhang".equals(req.getUsername()) && "123456".equals(req.getPassword())) {
//			StpUtil.login(req.getUsername(),req.getDeviceType());
            StpUserUtil.login(req.getUsername(), new SaLoginParameter()
                    .setDevice(req.getDeviceType())   // 此次登录的客户端设备类型, 用于[同端互斥登录]时指定此次登录的设备类型
                    .setIsLastingCookie(true)        // 是否为持久Cookie（临时Cookie在浏览器关闭时会自动删除，持久Cookie在重新打开后依然存在）
                    .setTimeout(60 * 60 * 24 * 7)    // 指定此次登录token的有效期, 单位:秒 （如未指定，自动取全局配置的 timeout 值）
                    .setIsWriteHeader(false)         // 是否在登录后将 Token 写入到响应头
            );
            LoginGetResp loginGetResp = new LoginGetResp();
            BeanUtils.copyProperties(req, loginGetResp);
            loginGetResp.setToken(StpUtil.getTokenInfo().getTokenValue());
            return SaResult.data(loginGetResp);
        }
        return SaResult.error("登录失败");
    }

    @Operation(summary = "查询登录状态")
    @GetMapping("isLogin")
    public SaResult isLogin() {
        return SaResult.ok("是否登录：" + StpUserUtil.isLogin());
    }
    /**
     * 登录认证(User版)：只有登录之后才能进入该方法
     * <p> 可标注在函数、类上（效果等同于标注在此类的所有方法上）
     */
    @SaUserCheckLogin()
    @Operation(summary = "获取token信息")
    @GetMapping("tokenInfo")
    public SaResult tokenInfo() {
        return SaResult.data(StpUserUtil.getTokenInfo());
    }

    @Operation(summary = "退出登录")
    @GetMapping("logout")
    public SaResult logout() {
        StpUserUtil.logout();
        return SaResult.ok();
    }

    /**
     * 强制注销等价于对方主动调用了注销方法，再次访问会提示：Token无效。
     * 踢人下线不会清除Token信息，而是将其打上特定标记，再次访问会提示：Token已被踢下线。
     */
    @Operation(summary = "强制注销")
    @GetMapping("logoutForce")
    public SaResult logoutForce(@Schema(description = "用户名") @RequestParam(name = "userName", defaultValue = "10001") String userName,
                                @Schema(description = "设备类型") @RequestParam(name = "deviceType", defaultValue = "PC") String deviceType) {
        StpUserUtil.logout(userName, deviceType);
        return SaResult.ok();
    }

    @Operation(summary = "踢人下线")
    @GetMapping("kickOut")
    public SaResult kickOut(@Schema(description = "用户名", required = true) @NotBlank(message = "用户名不能为空") @RequestParam(name = "userName", defaultValue = "10001") String userName,
                            @Schema(description = "设备类型") @RequestParam(name = "deviceType", defaultValue = "PC") String deviceType) {
        StpUserUtil.kickout(userName, deviceType);
        return SaResult.ok();
    }

}
